/**
 *******************************************************************************
 * \brief   CAS EBX Project Work "Kaffeemaschine"
 *
 * \file    rinse.c
 * \version 1.0
 * \date    30.06.2010
 * \author  Baehler Thomas, Liechti Beat, Sauter Marc
 * \author  Vuksic Valentina, Zbinden Rene
 *
 * \remark  Last Modifications:
 * \remark  V1.0, 30.06.2010   Initial release
 *******************************************************************************
 **/


/*
 *******************************************************************************
 * Definitions
 *******************************************************************************
 */
/** \brief The minimum amount of water needed for to rinse */
#define AMOUNT_OF_WATER 1


/*
 *******************************************************************************
 * Imports
 *******************************************************************************
 */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>
#include <unistd.h>

#include "coffee2.h"
#include "channel.h"
#include "pool.h"
#include "device.h"

/*
 *******************************************************************************
 * Local Variables
 *******************************************************************************
 */
static tChannel *c15; /*, *c33, *c34;*/
static tPool *p2, *p3;
static tDevice *d33, *d34;
static int timeExpired;

/*
 *******************************************************************************
 * Local Function Declaration
 *******************************************************************************
 */
static void sigtermHandler(int signal);
static void setTimeExpired(int signal);


/**
 *******************************************************************************
 * setTimeExpired
 *
 * \brief handle SIGALRM signal, set timeExpired
 *
 *******************************************************************************
 **/
static void setTimeExpired(int signal) {
	timeExpired = 1;
	return;
}


/**
 *******************************************************************************
 * sigtermHandler
 *
 * \brief handle SIGTERM signal, close all pools and channels and exit
 *
 *******************************************************************************
 **/
static void sigtermHandler(int signal) {
	syslog(LOG_INFO, "SIGTERM reveiced, stopping ...");
	/* open channels and pools */
	closeChannel(c15);
	//closeChannel(c33);
	//closeChannel(c34);
	closeDevice(d33);
	closeDevice(d34);

	closePool(p2);
	closePool(p3);
	/* close syslog */
	closelog();
	/* close and remove the runfile */
	exit(EXIT_SUCCESS);
}


/**
 *******************************************************************************
 * mainRinse
 *
 * \brief Activity: "Spuehlen"
 *
 * \return pid
 *
 *******************************************************************************
 **/
pid_t mainRinse(){
	pid_t pid;
	sigset_t sigmask;
	struct sigaction sigtermAction;
	enum e_errors error = NO_ERROR;
	int order = 0;
	int parameter = 0;
	int on = 1, off = 0;
	int waterAmount = 0;

	pid = fork();
	if (pid == 0) {
		/* syslog */
		openlog("coffee-rinse", LOG_PID, LOG_DAEMON);
		/* block all signals other than SIGTERM */
		sigemptyset(&sigmask);
		sigaddset(&sigmask, SIGTERM);
		sigtermAction.sa_handler = sigtermHandler;
		sigtermAction.sa_mask = sigmask;
		if (sigaction(SIGTERM, &sigtermAction, NULL) == -1){
			syslog(LOG_ERR, "unable to setup signal handling!");
		}
		/* register alarm function */
		if (signal(SIGALRM, setTimeExpired) == SIG_ERR) {
			syslog(LOG_ERR, "can't register SIGALRM!");
		}
		/* open channels and pools */
		c15 = openChannelRead("C15", sizeof(int));  /* read from "Milch" */
		//c33 = openChannelRead("C33", sizeof(int));  /* read from
		//												"Spuehlwassermenge" */
		//c34 = openChannelWrite("C34", sizeof(int)); /* write to "Spuehlpumpe" */
		d33 = openDeviceRead("/dev/c2flshmtr");
		d34 = openDeviceWrite("/dev/c2flshpmp");
		p2 = openPool("P2", sizeof(parameter));     /* "Parameter" */
		p3 = openPool("P3", sizeof(error));         /* "Error" */

		while (1) {
			if (readChannel(c15, &order) > 0) {
				syslog(LOG_INFO, "order from C15 received");
				/* read the parameter */
				readFromPool(p2, &parameter);
				/* start the milk pump */
				syslog(LOG_INFO, "starting rinse water pump");
				//writeChannel(c34, &on);
				writeDevice(d34, on);
				/* wait until correct waterAmount is reached */
				syslog(LOG_INFO, "checking amount of water  ...");
				alarm(WAIT_FOR_WATER_TIMEOUT);
				//readChannel(c33, &waterAmount);
				readDevice(d33, &waterAmount);
				while (waterAmount < AMOUNT_OF_WATER   && timeExpired == 0) {
					usleep(500);
					//readChannel(c33, &waterAmount);
					readDevice(d33, &waterAmount);
				}
				alarm(0);
				if (timeExpired == 1){
					syslog(LOG_ERR, "rinse water pump defective");
					error = RINSE_TIMEOUT;
					/* water pump seems to be defective ... */
					writeToPool(p3, &error);
				}
				/* stop water pump */
				syslog(LOG_INFO, "stopping rinse water pump");
				//writeChannel(c34, &off);
				writeDevice(d34, off);
				/* no more activities at this end */
			}
			usleep(500);
		}
	}
	return pid;
}
